/**
 * 测试用例yml格式导出
 * Create by nongzhizhong on 2021/06/08
 */
const path = require('path');
const compressing = require('compressing');
const fs = require('fs-extra');
const moment = require('moment');
const files = require('../../../files');
const functions = require('../../../functions');
const BaseTestCasesExporter = require('../base-exporter');
const utility = require('./../../../utility');
const { ymlDataHandle } = require('./yml-data-handle');
const YML_VERSION = '4.0.18';

class YmlTestCasesExporter extends BaseTestCasesExporter {
  exportTestCases(progressIndicator) {
    const result = {
      cachePath: this.outputDir,
    };
    return new Promise((resolve, reject) => {
      this.spliteByFunction(null, progressIndicator)
        .then(() => {
          const fileName = `${this.project.projectName}-${this.version.versionName}.test-cases.yml.zip`;
          result.testsPath = path.join(this.outputDir, fileName);
          const testsDir = path.join(this.outputDir, this.project.projectName);
          return compressing.zip.compressDir(testsDir, result.testsPath);
        })
        .then(() => {
          resolve(result);
        })
        .catch(reject);
    });
  }

  handleFunction(func, file, typeSystem, versionDir) {
    if (!file.functions || (file.functions.length > 0
      && !file.functions.includes(func._id.toString()))) {
      return Promise.resolve();
    }
    return new Promise((resolve, reject) => {
      const matchFunctionName = func.functionName.match(/^(.*?)\(.*\)$/);
      const functionName = matchFunctionName ? matchFunctionName[1] : func.functionName;
      const testsPath = `${path.join(versionDir, file.path, functionName)}.yml`;
      const { fileId } = func;
      const templatePath = path.join(__dirname, '/template', 'tests.yml.dot');
      super.handleFunction(func, file, typeSystem, versionDir)
        .then(() => fs.ensureDir(path.dirname(testsPath)))
        .then(() => {
          const funcVariables = functions.getFunctionVariableJson(func.variables);
          const typeSystemData = files.getTypesJson(fileId, typeSystem);
          const functionYmlFomat = {
            testModule: path.basename(file.path),
            testobject: functionName,
            version: YML_VERSION,
            date: moment().format('YYYY-MM-DD'),
            manualStubs: {},
            stubs: {},
            variables: [],
            variableTypes: [],
            values: [],
            mallocDeclaration: [],
            funcVariableAndValueMessage: {
              input: {
                globalVariablesData: {},
                staticsData: {},
                mallocVariablesData: {},
                paramVariablesData: {},

              },
              output: {
                globalOutputData: {},
                staticsOutputData: {},
                mallocOutputData: {},
                returnValueData: {},

              },
              mallocVariables: [],
            },
            // 测试用例执行建议
            testExecSuggestions: [],
          };
          const functionYmlData = ymlDataHandle(
            func.tests,
            funcVariables,
            typeSystemData,
            matchFunctionName ? `${matchFunctionName[1]}()` : `${functionName}()`,
            functionYmlFomat,
            this.i18n
          );
          return utility.getDotTemplate(templatePath, functionYmlData);
        })
        .then((content) => {
          content = content.split('\r\n').filter((line) => line.trim().length > 0).join('\r\n');
          return utility.writeFile(content, utility.handleWindwowFileNameSpecialCharacters(testsPath));
        })
        .then(resolve)
        .catch(reject);
    });
  }

  /**
   * 按文件分割
   * @return {Promise}
   */
  spliteByFile(callback = null, progressIndicator) {
    return new Promise((resolve, reject) => {
      const result = {};
      this.spliteByProjectVersion((versionDir) => fs.ensureDir(versionDir))
        .then(({ projectDir, versionPath, versionType }) => {
          result.projectDir = projectDir;
          result.versionPath = versionPath;
          result.versionDir = versionPath;
          result.versionType = versionType;
          return this.filterSelectedFiles();
        })
        .then(() => this.createVersionInfoFile(result.projectDir, result.versionType, 'yml'))
        .then(() => this.handleFiles(this.fileIds, result.versionDir, callback, progressIndicator))
        .then(() => resolve(result))
        .catch(reject);
    });
  }
}

module.exports = YmlTestCasesExporter;
